// 语法：useEffect(setup, dependencies?)
// 目标： 1. useEffect的执行时机？
import { Button, Divider, Input } from 'antd';
import { useEffect, useState } from 'react';

const Child = (props: { name: string }) => {
  useEffect(() => {
    console.log('child-initial-useEffect'); // show（加载）的时候打印
    // 3.setup的cleanup函数什么时候会触发呢？
    // 3-1.组件卸载时，触发setup（副作用）函数返回的清理(cleanup)函数，类似componentWillUnmount
    // 确切说清理函数就是副作用函数运行之前，会清除上一次的副作用函数。先执行一次setup的cleanup，再执行setup初始化（此时不执行cleanup）
    // 3-2.组件更新前也会执行setup的cleanup 【setName操作验证，同理：先执行一次setup的cleanup，再执行setup初始化（此时不执行cleanup）】
    // 3-3场景应用.根据上面的触发时机规则，有一个应用场景：输入关键词，触发请求搜索列表接口，实时更新组件数据。
    const timer = setTimeout(() => {
      fetch('http://localhost:5173/?name=' + props.name);
    }, 500); // 加个延迟防抖-创建了timer，但是还没执行fetch就执行清除timer，实现了防抖效果
    return () => {
      // console.log('cleanup-Child组件unmount');  // !show(卸载)的时候打印
      console.log(props.name, 'cleanup-Child组件unmount'); // name改变的时候打印，注意打印的是上一次的值，因为先执行cleanup，再执行更新
      clearTimeout(timer);
    };
  }, [props.name]);
  return <div>Child子组件</div>;
};

const App = () => {
  // 1.验证目标1-操作DOM验证-组件加载完成时才执行
  // const app = document.getElementById('app') as HTMLDivElement;
  // console.log(app, 'APP'); // null

  // 2.验证目标1-改变组件数据状态触发
  const [count, setCount] = useState(0);
  const [keyword, setKeyword] = useState('');

  // 3.验证目标1-组件卸载的时候触发 setupd的清理函数cleanup
  const [isShow, setIsShow] = useState(true);
  const [name, setName] = useState('');
  /**
   * @description: React 中用于处理副作用的钩子 https://zh-hans.react.dev/reference/react/useEffect
   * @param {Function} setup 处理 Effect (副作用)的函数。setup 函数选择性返回一个 清理（cleanup） 函数。
   * @param {any} dependencies setup 代码中引用的所有响应式值的列表。响应式值包括 props、state 以及所有直接在组件内部声明的变量和函数。
   * @return {*} 返回新的state，数据类型看默认值
   */
  useEffect(() => {
    // 1.组件加载完成之后执行。能取到dom节点，进而可以进行操作dom。类似componentDidMount
    // const appT = document.getElementById('app') as HTMLDivElement;
    // console.log(appT, 'APPT'); // 得到DOM节点
    // 2.改变组件data时执行。类似componentDidUpdate
    // console.log(count, 'init-useEffect');
    // console.log(keyword, 'init-useEffect');
    // 2-1.添加dependencies 依赖项【响应式值的列表】
    // 依赖项为空，useEffect只会在组件挂载时执行一次。类似componentDidMount 实际场景：初始化，详情页数据
    // 依赖项不为空，useEffect会根据依赖项变化执行。类似componentDidUpdate;例如指定count依赖项改变。是个数组可指定多个依赖项[]
    // 3.组件卸载的时候触发，返回一个清理(cleanup)函数也触发，类似componentWillUnmount-代码见Child组件
  });

  return (
    <>
      <div id="app">
        <h3>7-5.使用useEffect</h3>
        <div>
          <Button type="primary" onClick={() => setCount(count + 1)}>
            {count}
          </Button>
          <Divider />
          <Input
            placeholder="Basic usage"
            value={keyword}
            onChange={(e) => setKeyword(e.target.value)}
          />
          <Divider />
          <Input
            placeholder="改写子组件名称"
            value={name}
            onChange={(e) => setName(e.target.value)}
          />
          <Button onClick={() => setIsShow(!isShow)}>
            {isShow ? '隐藏' : '显示'}
          </Button>
          {/* 子组件 */}
          {isShow && <Child name={name} />}
        </div>
      </div>
    </>
  );
};

export default App;
